#include "SendTcpPacket.h"

//===========================================================================
//
// sendTCPreset()
// 				Parameters: (1) src_port - source port
//							(2) dest_port - destination port
//							(3) s_ip - source IP
//							(4) d_ip - destination IP
//							(5) seq - sequence number
//
int sendTCPpacket(u_short src_port,u_short dest_port,const char *s_ip,const char *d_ip,unsigned int seq)
{
	int s;
	int j;
	char packet[PACKETSIZE], tmp1[16];
	struct ip_header *ip;
	struct tcp_header *tcp;
	struct in_addr src_ip;
	struct in_addr dest_ip;
	struct sockaddr_in s_in;
	u_char ttl=DEF_TTL, flagz=0;
	srand((u_int)time(NULL));
	memset(&src_ip,0,sizeof(struct in_addr));
	memset(&dest_ip,0,sizeof(struct in_addr));

    dest_ip.s_addr=inet_addr(d_ip);
	src_ip.s_addr =inet_addr(s_ip);

	int sm=1;
	const int *val=&sm;

	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == SOCKET_ERROR)
	{
		perror("socket() is failed!");
	}
	setsockopt(s, IPPROTO_IP, IP_HDRINCL, val, sizeof(sm));

	ip = (struct ip_header *)packet;
  	tcp = (struct tcp_header *)(packet+sizeof(struct ip_header));

	memset(&s_in,0,sizeof(s_in));
	s_in.sin_family = AF_INET;
	s_in.sin_addr = dest_ip;
	s_in.sin_port = htons(dest_port);
	strncpy(tmp1,inet_ntoa(src_ip),sizeof(tmp1));
	create_ip(ip, src_ip, dest_ip, 15,ttl);
	create_tcp(tcp, src_port, dest_port, src_ip, dest_ip,seq,33, RST, DEF_WIN);


	if (sendto(s,packet,sizeof(packet),0,(struct sockaddr *)&s_in,sizeof(s_in)) == SOCKET_ERROR)
	{
		perror("Sendto is failed!\n");
	}

	if( close(s)==SOCKET_ERROR )
	{
		perror("Failed to close socket!\n");
		exit(1);
	}

	return 0;
}



//===========================================================================
//
// checksum() - calculates the checksum of the TCP segment
//			Parameters: (1) buffer - pointer to char buffer that holds the packet
//						(2) size of that buffer
//
u_short checksum(u_short *buffer, int size)
{
	u_long cksum=0;
	while (size > 1)
	{
		cksum += *buffer++;
        size  -= sizeof(u_short);
	}

    if (size) cksum += *(u_char *)buffer;
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);
	return (u_short)(~cksum);
}


//===========================================================================
//
// create_ip() - creates the IP header of the packet
//				Parameters: (1) hdr - pointer to struct ip_header
//							(2) srcaddr - pointer to struct in_addr srcaddr
//							(3) destaddr - pointer to struct in_addr srcaddr
//							(4) id - the IP Identification
//							(5) ttl - time to live
//
void create_ip(struct ip_header *hdr, struct in_addr srcaddr, struct in_addr destaddr, u_short id, u_char ttl)
{
	memset(hdr,0,sizeof(struct ip_header));
	hdr->ver = IPVER;
	hdr->len = 5;
	hdr->tot_len = htons(PACKETSIZE);
	hdr->id = htons(id);
	hdr->ttl = ttl;
	hdr->proto = IPPROTO_TCP;
	hdr->src_addr = srcaddr.s_addr;
	hdr->dest_addr = destaddr.s_addr;
	hdr->sum = 0;
}

//===========================================================================
//
// create_tcp()
//				Parameters: (1) hdr - pointer to struct tcp_header
//							(2) srcport - source port
//							(3) destport - destination port
//							(4) srcaddr -  source address
//							(5) destaddr - destination address
//							(6) seq - sequence numbrt
//							(7) ack - ack number
//							(8) flags - the 8 bits tcp flags
//							(9) win - the windos size (in bytes)
//
void create_tcp(struct tcp_header *hdr, u_short srcport, u_short destport, struct in_addr srcaddr, struct in_addr destaddr, u_int seq, u_int ack, u_char flags, u_short win)
{
	char *pseudo_packet;
	memset(hdr,0,sizeof(struct tcp_header));
	hdr->src_port = htons(srcport);
	hdr->dest_port = htons(destport);
	hdr->seq = htonl(seq);
	hdr->ack = htonl(ack);
	hdr->offset = DEF_OFFSET;
	hdr->window = htons(win);
	hdr->flags = flags;

	pseudo.src_addr = srcaddr;
	pseudo.dest_addr = destaddr;
	pseudo.zero = 0;
	pseudo.protocol = IPPROTO_TCP;
	pseudo.length = htons(sizeof(struct tcp_header));

	if ((pseudo_packet = (char *)malloc(PSEUDOSIZE)) == NULL)
	{
		perror("Malloc is failed!\n");
	}
	memcpy(pseudo_packet, &pseudo, sizeof(pseudo));
	memcpy(pseudo_packet+sizeof(pseudo), hdr, sizeof(struct tcp_header));
	hdr->sum = (u_short)checksum((u_short *)pseudo_packet, PSEUDOSIZE);
	free(pseudo_packet);
}





